package com.cskaoyan.wordmemorize.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cskaoyan.wordmemorize.common.aspect.operate.OperateLog;
import com.cskaoyan.wordmemorize.common.aspect.operate.OperateLogConstant;
import com.cskaoyan.wordmemorize.common.constant.ResultCodeEnum;
import com.cskaoyan.wordmemorize.common.exception.BusinessException;
import com.cskaoyan.wordmemorize.converter.VocCategoryConverter;
import com.cskaoyan.wordmemorize.dao.entity.VocBookDO;
import com.cskaoyan.wordmemorize.dao.entity.VocCategoryDO;
import com.cskaoyan.wordmemorize.dao.mapper.VocBookMapper;
import com.cskaoyan.wordmemorize.dao.mapper.VocCategoryMapper;
import com.cskaoyan.wordmemorize.dto.admin.DeleteBookCategoryOperateDTO;
import com.cskaoyan.wordmemorize.dto.admin.DeleteBookOperateDTO;
import com.cskaoyan.wordmemorize.dto.admin.PageDTO;
import com.cskaoyan.wordmemorize.dto.admin.VocCategoryDTO;
import com.cskaoyan.wordmemorize.request.BatchDeleteCommand;
import com.cskaoyan.wordmemorize.request.PageRequest;
import com.cskaoyan.wordmemorize.request.VocCategoryCommand;
import com.cskaoyan.wordmemorize.service.VocBookService;
import com.cskaoyan.wordmemorize.service.VocCategoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class VocCategoryServiceImpl implements VocCategoryService {

    @Autowired
    VocCategoryMapper vocCategoryMapper;

    @Autowired
    VocCategoryConverter vocCategoryConverter;

    @Autowired
    VocBookMapper vocBookMapper;

    @Autowired
    VocBookService vocBookService;

    @Override
    public PageDTO<VocCategoryDTO> getBookCategories(PageRequest pageQuery) {

        if (pageQuery.getPageNum() == null) {
            List<VocCategoryDO> vocCategoryDOS = vocCategoryMapper.selectList(null);

            return vocCategoryConverter.bookCategoryList2Page(vocCategoryDOS, (long) vocCategoryDOS.size());
        }
        Page<VocCategoryDO> pageParam = new Page<>(pageQuery.getPageNum(), pageQuery.getCount());
        LambdaQueryWrapper<VocCategoryDO> vocCategoryWrapper = new LambdaQueryWrapper<>();
        if (pageQuery.getKeyword() != null) {
            vocCategoryWrapper.like(VocCategoryDO::getCategoryName, pageQuery.getKeyword());
        }
        Page<VocCategoryDO> vocCategoryDOPage = vocCategoryMapper.selectPage(pageParam, vocCategoryWrapper);

        return vocCategoryConverter.bookCategoryList2Page(vocCategoryDOPage.getRecords(), vocCategoryDOPage.getTotal());

    }

    @Override
    public VocCategoryDTO getBookCategory(Long categoryId) {
        VocCategoryDO vocCategoryDO = vocCategoryMapper.selectById(categoryId);

        return vocCategoryConverter.bookCategoryEntity2DTO(vocCategoryDO);
    }

    @Override
    @OperateLog(dateType = "类目", operateType = OperateLogConstant.OPERATE_ADD)
    public Long addBookCategory(VocCategoryCommand command) {
        LambdaQueryWrapper<VocCategoryDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(VocCategoryDO::getCategoryName, command.getCategoryName());

        VocCategoryDO vocCategoryDO = vocCategoryMapper.selectOne(queryWrapper);
        if (vocCategoryDO != null) {
            throw new RuntimeException("分类已存在");
        }
        VocCategoryDO vocCategory = vocCategoryConverter.bookCategoryCommand2Entity(command);
        vocCategoryMapper.insert(vocCategory);
        return vocCategory.getId();
    }

    @Override
    @OperateLog(dateType = "类目", operateType = OperateLogConstant.OPERATE_UPDATE)
    public void updateBookCategory(VocCategoryCommand command) {
        VocCategoryDO vocCategory = vocCategoryConverter.bookCategoryCommand2Entity(command);
        vocCategoryMapper.updateById(vocCategory);
    }

    @Override
    @OperateLog(dateType = "类目", operateType = OperateLogConstant.OPERATE_SINGLE_DELETE)
    public DeleteBookCategoryOperateDTO deleteBookCategory(Long categoryId) {
        VocCategoryDO vocCategoryDO = vocCategoryMapper.selectById(categoryId);
        if (vocCategoryDO == null) {
            throw new BusinessException(ResultCodeEnum.BOOK_OFFLINE);
        }
        deleteBookByCategoryId(categoryId);
        vocCategoryMapper.deleteById(vocCategoryDO);
        return vocCategoryConverter.bookCategoryDOToDeleteCategoryDTO(vocCategoryDO);
    }

    @Override
    @OperateLog(dateType = "类目", operateType = OperateLogConstant.OPERATE_BATCH_DELETE)
    public List<DeleteBookCategoryOperateDTO> deleteBookCategories(BatchDeleteCommand command) {
        List<Long> ids = command.getIds().stream()
                .map(Long::parseLong)
                .collect(Collectors.toList());
        List<VocCategoryDO> vocCategoryDOS = vocCategoryMapper.selectByIds(ids);

        List<DeleteBookCategoryOperateDTO> resultList = new ArrayList<>();
        for (Long categoryId : ids) {
            deleteBookByCategoryId(categoryId);
        }

        List<DeleteBookCategoryOperateDTO> deleteBookCategoryOperateDTOS
                = vocCategoryConverter.bookCategoryDOsToDeleteCategoryDTOs(vocCategoryDOS);
        vocCategoryMapper.deleteByIds(ids);
        return deleteBookCategoryOperateDTOS;
    }

    private void deleteBookByCategoryId(Long categoryId) {
        LambdaQueryWrapper<VocBookDO> bookDOWrapper = new LambdaQueryWrapper<>();
        bookDOWrapper.select(VocBookDO::getId)
                .eq(VocBookDO::getBcId, categoryId);
        List<Long> bookIds = vocBookMapper.selectObjs(bookDOWrapper)
                .stream()
                .map(id -> (Long) id)
                .collect(Collectors.toList());

        if (!bookIds.isEmpty()) {
            BatchDeleteCommand command = new BatchDeleteCommand();
            command.setIds(bookIds.stream()
                    .map(String::valueOf) // Long转String
                    .collect(Collectors.toList()));
            vocBookService.deleteVocBooks(command);
        }
    }
}
